package main

import (
    "os"
    "path/filepath"
    "io/ioutil"
    "sync/atomic"
    "gopkg.in/yaml.v2"
)

type CommonConfig struct {
    MaxConn     int `yaml:"mcc"`
    HBTimeout   int64 `yaml:"hb_timeout"`
}

func newCommonConfig() *CommonConfig {
    c := &CommonConfig{}
    c.MaxConn = 3
    c.HBTimeout = 10
    return c
}

type HttpApiConfig struct {
    ListenAddr  string `yaml:"listen"`
    KeyFile     string `yaml:"cert_key"`
    CrtFile     string `yaml:"cert_crt"`
}

func newHttpApiConfig() *HttpApiConfig {
    c := &HttpApiConfig{}
    c.ListenAddr = ":6300"
    c.KeyFile = "/etc/desktop-gateway/cert/rh.key"
    c.CrtFile = "/etc/desktop-gateway/cert/rh.crt"
    return c
}

type TcpProxyConfig struct {
    ListenAddr  string `yaml:"listen"`
    Balance     string `yaml:"balance"`
    Server      []string `yaml:"server"`
    hashTable   *CHashTable
}

func (c *TcpProxyConfig) init() {
    if c.Balance == "hash" {
        c.hashTable = newCHashTable()
        c.hashTable.init(c.Server)
    }
}

type RdpProxyConfig struct {
    ListenAddr  string `yaml:"listen"`
    PassWord    string `yaml:"password"`
}

func newRdpProxyConfig() *RdpProxyConfig {
    c := &RdpProxyConfig{}
    c.ListenAddr = ":6192"
    c.PassWord = ""
    return c
}

type HttpProxyConfig struct {
    ListenAddr  string `yaml:"listen"`
    Server      []string `yaml:"server"`
    HeadExtend  string `yaml:"header-extend"`
}

type Config struct {
    RdpProxy    *RdpProxyConfig `yaml:"rdp_proxy"`
    TcpProxy    []*TcpProxyConfig `yaml:"tcp_proxy"`
    HttpApi     *HttpApiConfig `yaml:"http_api"`
    Common      *CommonConfig `yaml:"common"`
    HttpProxy   []*HttpProxyConfig `yaml:"http_proxy"`
}

func newConfig() *Config {
    c := &Config{}
    c.RdpProxy = newRdpProxyConfig()
    c.TcpProxy = make([]*TcpProxyConfig, 0)
    c.HttpApi = newHttpApiConfig()
    c.Common = newCommonConfig()
    c.HttpProxy = make([]*HttpProxyConfig, 0)
    return c
}

func (c *Config) loadFromFile() error {
    body, err := ioutil.ReadFile(configFile)
    if err != nil {
        return err
    }
    
    err = yaml.Unmarshal(body, c)
    if err != nil {
        return err
    }
    
    for _, c := range c.TcpProxy {
        c.init()
    }
    
    return nil
}

var gConfig atomic.Value

func configInit() {
    os.MkdirAll(filepath.Dir(configFile), 0755)
    
    c := newConfig()
    gConfig.Store(c)
}

func getConfig() *Config {
    c := gConfig.Load()
    if c == nil {
        return nil
    }
    
    return c.(*Config)
}

func loadConfig() {
    c := newConfig()
    err := c.loadFromFile()
    if err != nil {
        mainLog.Printf("load config from file failed. err(%v)\n", err)
        return
    }
    
    gConfig.Store(c)
}